﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Utils.Log
{ /// <summary>
  /// 稳定高效的日志(并不)
  /// </summary>
    public static class Log
    {
        /// <summary>
        /// 日志写入线程
        /// </summary>
        public static LogWorker logWorker;

        public static long Info_count { get; private set; } = 0;
        public static long Warning_count { get; private set; } = 0;
        public static long Error_count { get; private set; } = 0;
        public static string Log_folder_path { get; private set; }

        static Log()
        {
            Log_folder_path = Properties.Settings.Default.日志路径;
            //创建文件夹
            if (!Directory.Exists(Log_folder_path))
                Directory.CreateDirectory(Log_folder_path);
            //压缩日志
            ZipLog(TimeSpan.FromDays(7), 7, Log_folder_path, "*.log", "*.csv");

            logWorker = new LogWorker(Log_folder_path);
            logWorker.Start();
        }
        
        /// <summary>
        /// 直接写日志到日志队列(无类型)
        /// </summary>
        /// <param name="s">日志文本</param>
        public static void Write(dynamic s)
        {
            logWorker.Write(s);
        }

        /// <summary>
        /// 写日志到日志队列(通知)
        /// </summary>
        /// <param name="s">日志文本</param>
        public static void Info(dynamic s)
        {
            logWorker.Write("[Info]" + s);
            Info_count++;
        }

        /// <summary>
        /// 写日志到日志队列(警告)
        /// </summary>
        /// <param name="s">日志文本</param>
        public static void Warning(dynamic s)
        {
            logWorker.Write("[Warning]" + s);
            Warning_count++;
        }
        /// <summary>
        /// 写日志到日志队列(错误)
        /// </summary>
        /// <param name="s">日志文本</param>
        public static void Error(dynamic s)
        {
            logWorker.Write("[Error]" + s);
            Error_count++;
        }

        public static bool ChangeLogPath(string path)
        {
            if(!Directory.Exists(path))
            {
                try
                {
                    Directory.CreateDirectory(path);

                }catch(Exception e)
                {
                    Error(e.ToString());
                    return false;
                }
            }
            Log_folder_path = path;
            Properties.Settings.Default.配置项路径 = path;
            logWorker.Log_folder_path = path;
            Properties.Settings.Default.Save();
            return true;
        }
        /// <summary>
        /// 停止日志线程
        /// </summary>
        public static void Stop()
        {
            logWorker.Cancel();
        }

        public static string LogPath()
        {
            return logWorker.Log_path;
        }

        /// <summary>
        /// 压缩日志文件, 填入文件后缀名如*.log(不填则默认压缩*.log)
        /// </summary>
        /// <param name="how_long">多久之前</param>
        /// <param name="period">周期,即每x天一个压缩包</param>
        /// <param name="folder_path">文件夹路径</param>
        /// <param name="patterns">文件后缀列表</param>
        public static void ZipLog(TimeSpan how_long, int period, string folder_path, params string[] patterns)
        {
            Task.Run(new Action(() =>
            {
                if (patterns.Length == 0)
                    patterns = new string[] { "*.log" };
                //创建临时文件夹
                string temp_folder = folder_path + @"\temp";

                Directory.CreateDirectory(temp_folder);

                foreach (string pattern in patterns)
                {
                    string 后缀名 = pattern.Split('.').Last();
                    //过期日志文件列表
                    List<FileInfo> outdated_files = new List<FileInfo>();
                    //过期时间
                    DateTime outdated_time = DateTime.Now - how_long;
                    //筛选过期日志文件并排序
                    outdated_files = Directory.EnumerateFiles(folder_path, pattern, SearchOption.AllDirectories)
                        .Select(f => new FileInfo(f))
                        .Where(f => f.LastWriteTime < outdated_time)
                        .OrderBy(f => f.LastWriteTime)
                        .ToList();
                    //日志文件按周期分组
                    int groups = 0;
                    if (outdated_files.Count != 0)
                    {
                        groups = (int)Math.Floor((double)(outdated_files.Last().LastWriteTime - outdated_files.First().LastWriteTime).Days / period);
                    }
                    var first_date = outdated_files.First().LastWriteTime.Date;
                    for (int i = 0; i < groups; i++)
                    {
                        DateTime period_start = first_date + TimeSpan.FromDays(i * period);
                        DateTime period_end = period_start.AddDays(period);
                        List<FileInfo> t_list = outdated_files.Where(f => period_start <= f.LastWriteTime && f.LastWriteTime < period_end).ToList();
                        if (t_list.Count == 0)
                            continue;
                        //日志压缩文件名:20180101-20180102.zip
                        string zip_name = folder_path + @"\" + period_start.ToString("yyyyMMdd") + "-" + period_end.ToString("yyyyMMdd") + "." + 后缀名 + ".zip";
                        t_list.ForEach(f => f.MoveTo(temp_folder + @"\" + f.Name));
                        try
                        {
                            if (File.Exists(zip_name))
                                File.Delete(zip_name);
                            System.IO.Compression.ZipFile.CreateFromDirectory(temp_folder, zip_name);
                        }
                        catch (IOException e)
                        {
                            Write(e.ToString());
                        }
                        Directory.EnumerateFiles(temp_folder, pattern, SearchOption.TopDirectoryOnly).ToList().ForEach(f => File.Delete(f));
                    }
                }
                if (Directory.Exists(temp_folder))
                    Directory.Delete(temp_folder);
            }));

        }

    }
}
